﻿using HardcoreGame.Common.GlobalProjectiles;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using Terraria;
using Terraria.Audio;
using Terraria.GameContent;
using Terraria.ID;
using Terraria.ModLoader;

namespace HardcoreGame.Content.Projectiles.Sentries
{
    public class SkeletonSniper : ModProjectile
    {
        public bool shouldApplyESBuffs = true;
        public float shootCool = 0;
        public bool canDoStartup = true;
        public bool shouldPlayFiringAnimation = false;
        public bool canShoot = false;
        public int lookingDirection = 0;
        public bool isHacking = false;

        public override void SetStaticDefaults()
        {
            Main.projFrames[Projectile.type] = 11;
            ProjectileID.Sets.MinionTargettingFeature[Projectile.type] = true;
        }
        public override void SetDefaults()
        {
            Projectile.width = 32;
            Projectile.height = 60;
            Projectile.friendly = true;
            Projectile.sentry = true;
            Projectile.timeLeft = Projectile.SentryLifeTime;
            Projectile.ignoreWater = true;
            Projectile.tileCollide = true;
            Projectile.penetrate = -1;
        }

        public override bool PreDraw(ref Color lightColor)
        {
            Vector2 vector43 = Projectile.position + new Vector2(Projectile.width, Projectile.height) / 2f + Vector2.UnitY * Projectile.gfxOffY - Main.screenPosition;
            Texture2D texture2D33 = TextureAssets.Projectile[Projectile.type].Value;
            Texture2D textureGlow = ModContent.Request<Texture2D>(Texture + "_Glow").Value;
            Rectangle rectangle17 = texture2D33.Frame(1, Main.projFrames[Projectile.type], 0, Projectile.frame);
            Color alpha5 = Projectile.GetAlpha(lightColor);
            Vector2 origin11 = rectangle17.Size() / 2f;
            SpriteEffects spriteEffects = SpriteEffects.None;
            if (Projectile.spriteDirection == -1)
            {
                spriteEffects = SpriteEffects.FlipHorizontally;
            }
            Color color = new(255, 255, 255, Projectile.alpha);
            Main.spriteBatch.Draw(texture2D33, vector43, rectangle17, alpha5, Projectile.rotation, origin11, Projectile.scale, spriteEffects, 0f);
            Main.spriteBatch.Draw(textureGlow, vector43, rectangle17, color, Projectile.rotation, origin11, Projectile.scale, spriteEffects, 0f);
            return false;
        }
        public override bool? CanHitNPC(NPC target)
        {
            return false;
        }
        public override bool CanHitPlayer(Player target)
        {
            return false;
        }
        public override bool CanHitPvp(Player target)
        {
            return false;
        }

        public override bool? CanCutTiles()
        {
            return false;
        }

        public override bool OnTileCollide(Vector2 oldVelocity)
        {
            return false;
        }

        public override bool TileCollideStyle(ref int width, ref int height, ref bool fallThrough, ref Vector2 hitboxCenterFrac)
        {
            fallThrough = false;
            height = Projectile.height - 4;
            return true;
        }

        private int CustomFlameBurst_FindTarget_NoAngleLimit(float shot_range, Vector2 shootingSpot, bool canChangeDirection = true)
        {
            int num = -1;
            NPC ownerMinionAttackTargetNPC = Projectile.OwnerMinionAttackTargetNPC;
            if (ownerMinionAttackTargetNPC != null && ownerMinionAttackTargetNPC.CanBeChasedBy(this, false))
            {
                for (int i = 0; i < 1; i++)
                {
                    if (ownerMinionAttackTargetNPC.CanBeChasedBy(this, false))
                    {
                        float num2 = Vector2.Distance(shootingSpot, ownerMinionAttackTargetNPC.Center);

                        num2 *= 0.5f;

                        if (num2 <= shot_range)
                        {
                            Vector2 vector = (ownerMinionAttackTargetNPC.Center - shootingSpot).SafeNormalize(Vector2.UnitY);
                            if ((canChangeDirection || Projectile.direction * vector.X >= 0f) && (num == -1 || num2 < Vector2.Distance(shootingSpot, Main.npc[num].Center)) && Collision.CanHitLine(shootingSpot, 0, 0, ownerMinionAttackTargetNPC.Center, 0, 0))
                            {
                                num = ownerMinionAttackTargetNPC.whoAmI;
                            }
                        }
                    }
                }
                if (num != -1)
                {
                    return num;
                }
            }
            for (int j = 0; j < 200; j++)
            {
                NPC nPC = Main.npc[j];
                if (nPC.CanBeChasedBy(this, false))
                {
                    float num3 = Vector2.Distance(shootingSpot, nPC.Center);
                    if (num3 <= shot_range)
                    {
                        Vector2 vector2 = (nPC.Center - shootingSpot).SafeNormalize(Vector2.UnitY);
                        if ((canChangeDirection || Projectile.direction * vector2.X >= 0f) && (num == -1 || num3 < Vector2.Distance(shootingSpot, Main.npc[num].Center)) && Collision.CanHitLine(shootingSpot, 0, 0, nPC.Center, 0, 0))
                        {
                            num = j;
                        }
                    }
                }
            }
            return num;
        }


        public override void AI()
        {
            Projectile.velocity.Y += 0.2f;

            if (Projectile.velocity.Y > 16f)
            {
                Projectile.velocity.Y = 16f;
            }

            float shot_range = 4000f;
            float shootCoolMax = 50;
            bool hasTarget = false;
            Vector2 center = Projectile.Center;
            float shootSpeed = 16f;
            if (shootCoolMax < 25)
            {
                shootCoolMax = 25;
            }
            if (shootCool > 0f)
            {
                shootCool--;
            }
            if (canDoStartup)
            {
                lookingDirection = 0;
                shootCool = shootCoolMax;
                Projectile.direction = Projectile.spriteDirection = Main.player[Projectile.owner].direction;
                Projectile.spriteDirection = Projectile.direction;
                Projectile.ai[0] = 1f;
                canDoStartup = false;
                Projectile.netUpdate = true;
                SoundEngine.PlaySound(SoundID.Item6.WithVolumeScale(0.5f), Projectile.Center);
                for (int num68 = 0; num68 < 70; num68++)
                {
                    Dust obj7 = Main.dust[Dust.NewDust(Projectile.position, Projectile.width, Projectile.height, DustID.MagicMirror, Projectile.velocity.X * 0.2f, Projectile.velocity.Y * 0.2f, 150, Color.Cyan, 1.2f)]; ;
                    obj7.velocity *= 0.5f;
                }
            }

            if (!canDoStartup && !hasTarget)
            {
                int myTarget = CustomFlameBurst_FindTarget_NoAngleLimit(shot_range, center, true);
                if (myTarget != -1)
                {
                    float dist = Vector2.Distance(Main.npc[myTarget].Center, center);
                    if (dist < 0)
                    {
                        dist = 0.1f;
                    }
                    float predictionMult = dist / (shootSpeed * 13);
                    if (predictionMult < 1)
                    {
                        predictionMult = 1f;
                    }
                    Vector2 predictedLocation = Main.npc[myTarget].Center + Main.npc[myTarget].velocity * predictionMult;
                    Projectile.direction = Math.Sign(Projectile.DirectionTo(Main.npc[myTarget].Center).X);
                    hasTarget = true;
                    Projectile.netUpdate = true;
                    if (!shouldPlayFiringAnimation && !isHacking)
                    {
                        float targetCenterXCompared = predictedLocation.X - Projectile.Center.X;
                        float targetCenterYCompared = predictedLocation.Y - Projectile.Center.Y;

                        if (!(targetCenterYCompared > 0f))
                        {
                            if (!(Math.Abs(targetCenterXCompared) > Math.Abs(targetCenterYCompared) * 2f))
                            {
                                lookingDirection = 3;
                            }
                            else
                            {
                                lookingDirection = 1;
                            }
                            if (Math.Abs(targetCenterYCompared) > Math.Abs(targetCenterXCompared) * 2f)
                            {
                                lookingDirection = 5;
                            }
                        }
                        else
                        {
                            if (Math.Abs(targetCenterYCompared) > Math.Abs(targetCenterXCompared) * 2f)
                            {
                                lookingDirection = 9;
                            }
                            else if (!(Math.Abs(targetCenterXCompared) > Math.Abs(targetCenterYCompared) * 2f))
                            {
                                lookingDirection = 7;
                            }
                            else
                            {
                                lookingDirection = 1;
                            }
                        }
                    }
                }
                else if (shootCool == 0)
                {
                    lookingDirection = 0;
                }
            }

            if (hasTarget)
            {
                if (!shouldPlayFiringAnimation && !isHacking)
                {
                    Projectile.spriteDirection = Projectile.direction;
                }

                if (shootCool <= 0)
                {
                    int myTarget3 = CustomFlameBurst_FindTarget_NoAngleLimit(shot_range, center, false);
                    if (myTarget3 == -1)
                    {
                        shouldPlayFiringAnimation = false;
                    }
                    else if (!shouldPlayFiringAnimation)
                    {
                        shouldPlayFiringAnimation = true;
                        canShoot = true;
                    }

                    if (myTarget3 != -1 && canShoot)
                    {

                        SoundEngine.PlaySound(new SoundStyle("HardcoreGame/Assets/Sounds/Projectiles/P_1"), Projectile.Center);
                        if (!Main.dedServ && Main.myPlayer != -1)
                        {
                            float distanceToSniper = Vector2.Distance(Main.player[Main.myPlayer].Center, Projectile.Center);
                            float distantVolume = 1f;
                            float soundRange = 10000;

                            if (distanceToSniper > 250f)
                            {
                                distantVolume = 1f - (distanceToSniper - 250) * (1 / soundRange);
                            }

                            if (distantVolume < 0f)
                            {
                                distantVolume = 0f;
                            }
                            if (distantVolume > 1f)
                            {
                                distantVolume = 1f;
                            }
                        }

                        Vector2 value = new(Projectile.direction, 0f);
                        int myTarget2 = CustomFlameBurst_FindTarget_NoAngleLimit(shot_range, center, false);

                        float dist = Vector2.Distance(Main.npc[myTarget2].Center, center);
                        if (dist < 0)
                        {
                            dist = 0.1f;
                        }
                        float predictionMult = dist / (shootSpeed * 13);
                        if (predictionMult < 1)
                        {
                            predictionMult = 1f;
                        }
                        Vector2 predictedLocation = Main.npc[myTarget2].Center + Main.npc[myTarget2].velocity * predictionMult;

                        if (myTarget2 != -1)
                        {
                            value = (predictedLocation - center).SafeNormalize(Vector2.UnitX * Projectile.direction);
                        }

                        Vector2 velocity = value * shootSpeed;
                        if (Projectile.owner == Main.myPlayer)
                        {
                            int bullet = Projectile.NewProjectile(Projectile.GetSource_FromAI(), center, velocity, ProjectileID.BulletHighVelocity, Projectile.damage, Projectile.knockBack, Projectile.owner, 0f, 0f);
                            Main.projectile[bullet].extraUpdates = 10;
                            Main.projectile[bullet].penetrate = 1;
                            Main.projectile[bullet].DamageType = DamageClass.Summon;
                            Main.projectile[bullet].minion = true;
                            Main.projectile[bullet].GetGlobalProjectile<MinionProjectile>().skeletonSniper = true;
                        }
                        Projectile.frame = lookingDirection;
                        shootCool = shootCoolMax;
                        canShoot = false;
                    }
                }
            }
            if (!isHacking)
            {
                if (shouldPlayFiringAnimation)
                {
                    Projectile.frameCounter++;
                    if (Projectile.frameCounter > 4)
                    {
                        Projectile.frameCounter = 0;
                        Projectile.frame++;
                    }

                    if (Projectile.frame > lookingDirection + 1)
                    {
                        shouldPlayFiringAnimation = false;
                        Projectile.frame = lookingDirection + 1;
                    }
                }
                else
                {
                    Projectile.frame = lookingDirection;
                }
            }
            else
            {
                lookingDirection = 5;

                if (shouldPlayFiringAnimation)
                {
                    Projectile.frameCounter++;
                    if (Projectile.frameCounter > 4)
                    {
                        Projectile.frameCounter = 0;
                        Projectile.frame++;
                    }

                    if (Projectile.frame > lookingDirection + 1)
                    {
                        shouldPlayFiringAnimation = false;
                        Projectile.frame = lookingDirection + 1;
                    }
                }
                else
                {
                    Projectile.frame = lookingDirection;
                }

                if (Projectile.localAI[0] == 0)
                {
                    Projectile.spriteDirection = (int)(Projectile.spriteDirection * -1f);
                    Projectile.localAI[0] = 3;
                }
                else
                {
                    Projectile.localAI[0]--;
                }
            }
        }

        public override void OnKill(int timeLeft)
        {
            SoundEngine.PlaySound(SoundID.Item6.WithVolumeScale(0.5f), Projectile.Center);
            for (int num68 = 0; num68 < 70; num68++)
            {
                Dust obj7 = Main.dust[Dust.NewDust(Projectile.position, Projectile.width, Projectile.height, DustID.MagicMirror, Projectile.velocity.X * 0.2f, Projectile.velocity.Y * 0.2f, 150, Color.Cyan, 1.2f)]; ;
                obj7.velocity *= 0.5f;
            }
        }
    }
}